﻿using System.IO;
using System.Diagnostics.Contracts;
using System.Text.RegularExpressions;

namespace SetVersionNumber.FileWriters {

	/// <summary>
	/// An abstract base class for 
	/// </summary>
	public abstract class RegexBaseVersionNumber : IFileUpdater {

		/// <summary>
		/// Create a new regular expression base version number checker
		/// </summary>
		/// <param name="fileNameMatchingRegularExpression">The file pattern that this file writer supports</param>
		/// <param name="regex">The regular expression text to use for the search and replace within the file.</param>
		protected RegexBaseVersionNumber( string fileNameMatchingRegularExpression, string regex ) {
			Contract.Requires(!string.IsNullOrWhiteSpace(fileNameMatchingRegularExpression), "The file extension should not be null or empty");
			_fileNameMatchingRegularExpression = fileNameMatchingRegularExpression;
			_regex = new Regex(regex, RegexOptions.IgnoreCase | RegexOptions.Compiled);
		}


		/// <summary>
		/// The file extensions this file writer will process
		/// </summary>
		/// <param name="fileName">The file name to test</param>
		/// <returns><c>true</c> if this file updater will process the given file, <c>false</c> if it will not.</returns>
		public bool WillProcessFile( string fileName ) {
			return Regex.IsMatch(fileName, _fileNameMatchingRegularExpression);
		}
		private readonly string _fileNameMatchingRegularExpression;


		/// <summary>
		/// Process the given file
		/// </summary>
		/// <param name="fileName">The file name to process</param>
		/// <param name="strategy">The version number strategy</param>
		public bool ProcessFile( string fileName, IVersionStrategy strategy ) {
			// Load in the entire file (they're usually not too large)
			var fileContents = File.ReadAllText(fileName);

			// Find the existing version number
			var matches = _regex.Matches(fileContents);
			if( matches.Count==0 )
				return false;

			// Now process each match
			int offset = 0;
			foreach( Match match in matches ) {
				// Get the group that contains the current version number
				var group = match.Groups[VERSION_GROUP_NAME];
				if( group==null ) return false;

				// Get the next version number to use
				string currentVersionNumber = group.Value;
				if( string.IsNullOrWhiteSpace(currentVersionNumber) ) return false;
				var newVersionNumber = strategy.GetNextVersionNumber(currentVersionNumber);

				// Cut out the old version number
				int index = group.Index + offset;
				fileContents = fileContents.Remove(index, group.Length);

				// Inject the new version number
				fileContents = fileContents.Insert(index, newVersionNumber);

				// Figure out where the next file change will be
				int deltaOffset = newVersionNumber.Length - group.Length;
				offset += deltaOffset;
			}//foreach

			// Write out the new text
			File.WriteAllText(fileName, fileContents);
			return true;
		}


		/// <summary>
		/// The regular expression used to replace the version number
		/// </summary>
		private readonly Regex _regex;


		/// <summary>
		/// The name of the version group within the regular expression
		/// </summary>
		protected const string VERSION_GROUP_NAME = "version";

	}//class

}//namespace
